package com.song.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 常用日期处理
 */
public class DateUtil {
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String DEFAULT_SHORT_DATE = "yyyy-MM-dd";

    private static final Integer MIN_HOUR = 0;
    private static final Integer MIN_MINUTE = 0;
    private static final Integer MIN_SECOND = 0;
    private static final Integer MAX_HOUR = 23;
    private static final Integer MAX_MINUTE = 59;
    private static final Integer MAX_SECOND = 59;

    /**
     * 字符串按默认格式转日期
     * @param source
     * @return
     * @throws ParseException
     */
    public static Date parse(String source) throws ParseException {
        return createDateFormat(DEFAULT_DATE_FORMAT).parse(source);
    }

    /**
     * 字符串按指定格式转日期
     * @param source
     * @param pattern
     * @return
     * @throws ParseException
     */
    public static Date parse(String source, String pattern) throws ParseException {
        return createDateFormat(pattern).parse(source);
    }

    /**
     * 日期按默认格式转字符串
     * @param date
     * @return
     */
    public static String format(Date date){
        if (date == null){
            throw new IllegalArgumentException("The date must not be null");
        }
        return createDateFormat(DEFAULT_DATE_FORMAT).format(date);
    }

    /**
     * 日期按指定格式转字符串
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date, String pattern){
        if (date == null){
            throw new IllegalArgumentException("The date must not be null");
        }
        return createDateFormat(pattern).format(date);
    }

    /**
     * 创建日期格式实现类
     * @param pattern
     * @return
     */
    public static SimpleDateFormat createDateFormat(String pattern){
        return new SimpleDateFormat(pattern);
    }

    /**
     * 指定日期增加年
     * @param date
     * @param amount
     * @return
     */
    public static Date addYear(Date date, int amount){
        return add(date, amount, Calendar.YEAR);
    }

    /**
     * 指定日期增加月
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonth(Date date, int amount){
        return add(date, amount, Calendar.MONTH);
    }

    /**
     * 指定日期增加天
     * @param date
     * @param amount
     * @return
     */
    public static Date addDay(Date date, int amount){
        return add(date, amount, Calendar.DATE);
    }

    /**
     * 指定日期增加周
     * @param date
     * @param amount
     * @return
     */
    public static Date addWeek(Date date, int amount){
        return add(date, amount, Calendar.WEEK_OF_YEAR);
    }

    /**
     * 指定日期减少天
     * @param date
     * @param amount
     * @return
     */
    public static Date reduceDay(Date date, int amount){
        return add(date, -amount, Calendar.DATE);
    }

    /**
     * 指定日期增加年、月、日、时、分、秒、毫秒、周
     * @param date
     * @param amount
     * @param field
     * @return
     */
    public static Date add(Date date, int amount, int field){
        if (date == null){
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar calendar = createCalendar(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 创建日历类
     * @param date
     * @return
     */
    public static Calendar createCalendar(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    /**
     * 获取指定日期星期几 0~6
     * @param date
     * @return
     */
    public static int getWeekOfDate(Date date){
        if (date == null){
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar calendar = createCalendar(date);
        return calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 获取时间戳
     * @param source
     * @return
     */
    public static Long getTimestamp(String source) throws ParseException {
        return createDateFormat(DEFAULT_DATE_FORMAT).parse(source).getTime();
    }

    /**
     * 获取日期时间戳
     * @param source
     * @return
     */
    public static Long getTimestampOfDay(String source) throws ParseException {
        return createDateFormat(DEFAULT_SHORT_DATE).parse(source).getTime();
    }

    /**
     * 获取一天的开始时间
     * @param date
     * @return
     */
    public static synchronized Date getDayStart(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, MIN_HOUR);
        calendar.set(Calendar.MINUTE, MIN_MINUTE);
        calendar.set(Calendar.SECOND, MIN_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一天的结束时间
     * @param date
     * @return
     */
    public static synchronized Date getDayEnd(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, MAX_HOUR);
        calendar.set(Calendar.MINUTE, MAX_MINUTE);
        calendar.set(Calendar.SECOND, MAX_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一年的开始时间
     * @param date
     * @return
     */
    public static synchronized Date getYearStart(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, MIN_HOUR);
        calendar.set(Calendar.MINUTE, MIN_MINUTE);
        calendar.set(Calendar.SECOND, MIN_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一年的结束时间
     * @param date
     * @return
     */
    public static synchronized Date getYearEnd(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, 1);
        calendar.set(Calendar.DAY_OF_YEAR, 0);
        calendar.set(Calendar.HOUR_OF_DAY, MAX_HOUR);
        calendar.set(Calendar.MINUTE, MAX_MINUTE);
        calendar.set(Calendar.SECOND, MAX_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一月的开始时间
     * @param date
     * @return
     */
    public static synchronized Date getMonthStart(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, MIN_HOUR);
        calendar.set(Calendar.MINUTE, MIN_MINUTE);
        calendar.set(Calendar.SECOND, MIN_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一月的结束时间
     * @param date
     * @return
     */
    public static synchronized Date getMonthEnd(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        calendar.set(Calendar.HOUR_OF_DAY, MAX_HOUR);
        calendar.set(Calendar.MINUTE, MAX_MINUTE);
        calendar.set(Calendar.SECOND, MAX_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一周的开始时间（以周一为一周的第一天）
     * @param date
     * @return
     */
    public static synchronized Date getWeekStart(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, MIN_HOUR);
        calendar.set(Calendar.MINUTE, MIN_MINUTE);
        calendar.set(Calendar.SECOND, MIN_SECOND);
        return calendar.getTime();
    }

    /**
     * 获取一周的结束时间（以周一为一周的第一天）
     * @param date
     * @return
     */
    public static synchronized Date getWeekEnd(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        calendar.set(Calendar.HOUR_OF_DAY, MAX_HOUR);
        calendar.set(Calendar.MINUTE, MAX_MINUTE);
        calendar.set(Calendar.SECOND, MAX_SECOND);
        return calendar.getTime();
    }

}
